package com.mapresso.gps;

import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.simplify.DouglasPeuckerLineSimplifier;

public class GpsManager {
	static final String msgVersion = "GpsGen 0.2";
	public GpsTrack track_original;
	public GpsTrack track;
	GpsTrack wayPoints;
	private double dmini_meter;
	public double minSpeed = 5.5, maxSpeed = 15.0;

	public GpsManager() {
		track_original = new GpsTrack();
		track = new GpsTrack();
	}

	GpsTrack readGpx(String filename, String dir) {
		String fnGpxfile = dir + filename;
		if (filename.toLowerCase().endsWith(".gpx")) {
			filename = filename.substring(0, filename.length() - 4);
		}
		GpsReader gpsRdr = new GpsReader(fnGpxfile);
		GpsTrack trackIn = new GpsTrack(gpsRdr);
		trackIn.meta.name = filename;
		trackIn.meta.author = "Adrian Herzog";
		return trackIn;
	}

	public void doRead (String filename, String dir) {
		GpsUtils.printAction("Reading " + filename + " (in: " + dir + ")");
		track_original = readGpx(filename, dir);
		track = track_original.copy();
	}
	
	void doStatistics000 () {
		track.doStatistics();
	}
	
	public void doSpeedLimits (double minSpeed0, double maxSpeed0) {
		minSpeed = minSpeed0;
		maxSpeed = maxSpeed0;
	}

	public void doSplit (int first, int last) {
		if (last <= first) {
			Log.error("first > last: " + first + " > " + last);
			return;
		}
		GpsUtils.printAction("Extraction of trackpoints " + first + " - " + last + ".");
		track = track.part(first, last);
		track.addDesc("split " + first + "-" + last);
	}

	public void doSave (String fileName) {
		GpsWriter.writeGpx(track, fileName);
	}

	public void writeKml(boolean compressed, String fileName) {
		GpsUtils.printAction("writing compressed KML: " + fileName);
		track.meta.desc = track.printKmlStatistics() + "; DP " + GpsUtils.format(dmini_meter, 2);
		GpsWriter.writeKml(track, fileName, compressed);
	}
	
	public void generalizeDP(double dmini) {
		GpsUtils.printAction("Douglas/Peucker with dmini: "
				+ (dmini * GpsUtils.angle2meter()) + " m (" + dmini + " radians).");
		if (dmini > 0.0) {
//			track = track.(dmini);
			track = GpsModeler.generalizeDP(track, dmini);
			track.doStatistics();
		}
	}


	public void doPlausi(double vmaxmax) {
//		if (vmaxmax == 0) vmaxmax = 2.0 * track.totalSpeed();
//		double vmax = Math.min(2.0 * track.totalSpeed(), vmaxmax);
		GpsUtils.printAction("Eleminating strange speeds (using maximal speed " + vmaxmax + " km/h).");
//		track.reduceToPlausibleSpeeds(vmax);
		track = GpsModeler.reduceToPlausibleSpeeds(track, vmaxmax);
		track.addDesc("vmax " + GpsUtils.format(vmaxmax, 1));
	}

	public void doPause(double vmin) {
		if (vmin == 0) vmin = track.totalSpeed() / 5.0;
		GpsUtils.printAction("Removing breaks (using minimal speed " + vmin + " km/h).");
		track = GpsModeler.reduceToPlausibleSpeedsPause(track, vmin);
		track.addDesc("vmin " + GpsUtils.format(vmin, 1));
	}

	void generalizeDP0(double dmini) {
		CoordinateTime[] coord = GpsUtils.path2coordTime(track);
		DouglasPeuckerLineSimplifier dpls = new DouglasPeuckerLineSimplifier(coord);
		dpls.setDistanceTolerance(dmini);
		Coordinate[] coord_gen = dpls.simplify();

		String name = track.meta.name;
		String desc = track.meta.desc;
		String author = track.meta.author;
		String email = track.meta.email;
		String keywords = track.meta.keywords;
		track = GpsUtils.coordTime2path(coord_gen, coord);
		track.meta.name = name;
		track.meta.desc = desc;
		track.meta.author = author;
		track.meta.email = email;
		track.meta.keywords = keywords;
		track.addDesc("DP " + GpsUtils.format(dmini_meter, 2));
		track.meta.name += "_g";
	}

	public void doPlausiMany(double dmini_meter_0) {
		double dmini = GpsUtils.meter2angle() * dmini_meter_0;
		System.out.println("dmini start: "
				+ dmini_meter_0 + " meter,  " + dmini + " radians.");
		if (dmini > 0.0) {
			System.out.println("\nLh\tL\tdmini\tN\tup\tdown\tchanges");
			double dist_h = Math.round(track.getLength()) +
			5.0 * track.ups - 2.0 * track.downs;
			System.out.println(Math.round(dist_h) + "\t" + Math.round(track.getLength())
					+ "\t" + 0.0 + "\t" + track.nPoints() 
					+ "\t" + track.ups + "\t" + track.downs + "\t" + track.n_changes);
			double fac = Math.sqrt(2.0);
			do {
				CoordinateTime[] coord = GpsUtils.path2coordTime(track);
				DouglasPeuckerLineSimplifier dpls = new DouglasPeuckerLineSimplifier(coord);
				dpls.setDistanceTolerance(dmini);
				Coordinate[] coord_gen = dpls.simplify();
				track = GpsUtils.coord2path(coord_gen);
				track.doStatistics();
				dist_h = Math.round(track.getLength()) +
				5.0 * track.ups - 2.0 * track.downs;
				System.out.println(Math.round(dist_h) + "\t" + Math.round(track.getLength())
						+ "\t" + GpsUtils.format(dmini_meter_0, 3) + "\t" + track.nPoints() 
						+ "\t" + GpsUtils.format(track.ups, 0) 
						+ "\t" + GpsUtils.format(track.downs, 0) + "\t" + track.n_changes);
				dmini_meter_0 *= fac;
				dmini = dmini_meter_0 * GpsUtils.meter2angle();
			} while (track.nPoints() > 3);
		}
	}

	public void doLog() {
		GpsUtils.printSeparatorline();
		System.out.println(track.toString());
		GpsUtils.printSeparatorline();
	}

	public void doReset() {
		GpsUtils.printAction("Reset, back to the original track.");
		track = track_original.copy();
	}

	public void doMetaLog() {
		GpsUtils.printSeparatorline();
		System.out.println(track.meta.toString());		
		GpsUtils.printSeparatorline();
	}


}
